/**
 * Copyright (c) 2009  Collaborative Development Group, C.S. Dept., University of Bari
 *
 * All rights reserved. This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License v1.0  which accompanies this distribution, and is 
 * available at http://www.eclipse.org/legal/epl-v10.html
 */
package it.uniba.di.cdg.penelope.ui.mvp;

import static it.uniba.di.cdg.penelope.util.ReflectionUtilities.getUnproxiedType;
import it.uniba.di.cdg.penelope.annotation.Start;
import it.uniba.di.cdg.penelope.annotation.Stop;
import it.uniba.di.cdg.penelope.events.EventHandlerInvocationException;

import java.beans.PropertyChangeEvent;
import java.lang.reflect.Method;

/**
 * A base implementation for {@link IPresenter}s. 
 */
public class AbstractPresenter implements IPresenter {
	/* (non-Javadoc)
	 * @see it.uniba.di.cdg.penelope.ui.mvp.IPresenter#onViewCreated()
	 */
	@Start
	public void onViewCreated() {
		// Nothing
	}
	
	/* (non-Javadoc)
	 * @see it.uniba.di.cdg.penelope.ui.mvp.IPresenter#onViewDisposed()
	 */
	@Stop
	public void onViewDisposed() {
		// nothing
	}

	/* (non-Javadoc)
	 * @see it.uniba.di.cdg.penelope.ui.mvp.IPresenter#dispatchEvent(it.uniba.di.cdg.penelope.ui.mvp.ViewEvent)
	 */
	public void dispatchEvent( ViewEvent viewEvent ) {
		// Dispatch the event to the appropriate methods.
		Class<?> eventType = viewEvent.getClass();
		Method method = getMethod( this.getClass(), eventType );
		if (method != null) {
			try {
				method.invoke( this, viewEvent );
			} catch (Throwable e) {
				throw new EventHandlerInvocationException( e );
			}
		}
	}
	
	/**
	 * Allows presenter to react to changes in the presentation model. If no implementation is provided, the default
	 * behavior is to do nothing.
	 * 
	 * @param evt the property change event 
	 */
	public void propertyChange( PropertyChangeEvent evt ) {
		// Do nothing by default
	}	

	private static Method getMethod( Class<?> delegateClass, Class<?> eventType ) {
		delegateClass = getUnproxiedType( delegateClass );
		
		Method[] methods = delegateClass.getMethods();
		for (Method method : methods) {
			if (method.getParameterTypes().length == 1 && method.getParameterTypes()[0].equals( eventType )) {
				return  method;
			}
		}
		return null;
	}
}
